package com.xiang.sql.service;

import java.time.LocalDate;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiang.WebSocket.WebSocketService;
import com.xiang.api.Util;
import com.xiang.api.entity.Message;
import com.xiang.api.service.WxService;
import com.xiang.sql.StaticSql;
import com.xiang.sql.entity.Addr;
import com.xiang.sql.entity.Group;
import com.xiang.sql.entity.Order;
import com.xiang.sql.entity.StockLog;
import com.xiang.sql.entity.User;
import com.xiang.sql.mapper.OrderMapper;
import com.xiang.sql.mapper.StockMapper;

import jakarta.annotation.Resource;

/**
 * 订单 服务实现类
 * 
 * @author mac-xiang
 */
@Service
public class OrderService extends ServiceImpl<OrderMapper, Order> {
  @Resource
  OrderMapper mapper;

  private QueryWrapper<Order> readWrapper(JSONObject p, User per) {
    QueryWrapper<Order> ret = Util.getQuery(p, Order.class, "a");
    if (per != null && !per.per("订单查询") && !per.per("强制发货")) {
      ret.and(e -> {
        e.eq("`create`", per.id).or().eq("`gid`", per.gid);
      });
    }
    Integer sdel = p.getInteger("showDel");
    if (sdel != null) {
      ret.eqSql("0", "a.`del`&" + sdel);
    }
    return ret;
  }

  private final static String limit = " LIMIT %d,%d";

  private List<Order> getList(QueryWrapper<Order> q) {
    List<Order> r = mapper.selectList2(q);
    r.forEach(e -> {
      e.content = StaticSql.service.stockLog.getByOid(e.id);
      // e.sx = e.sx == null || e.sx == 0 && e.payTime != null && e.payTime!= 0 ? 1:0;
      e.sx = e.payTime != null && e.payTime != 0 ? 1 : 0;
    });
    return r;
  }

  private List<Order> getList(JSONObject p, User per) {
    return getList(readWrapper(p, per));
  }

  private Page<Order> getPage(Page<Order> page, JSONObject p, User per) {
    QueryWrapper<Order> q = readWrapper(p, per);
    page.setTotal(mapper.count2(q));
    final long c = page.getCurrent(), s = page.getSize();
    List<Order> d = getList(readWrapper(p, per).last(String.format(limit, s * (c - 1), s)));

    page.setRecords(d);
    return page;
  }

  private Order createOrder(JSONObject p, User per) {
    Order entity = Util.getEntity(p, Order.class);
    if (entity.content == null || entity.content.size() < 1) {
      throw new RuntimeException("请重新下单");
    }
    entity.id = Util.sGetId();
    entity.gid = p.getString("gid");
    if (Util.isEmpty(entity.gid)) {
      entity.gid = "0";
    }
    entity.createTime = Util.time();
    entity.payTime = 0l;
    entity.sendTime = 0l;
    entity.recvTime = 0l;
    entity.recvAddr = p.getString("addr");
    if (Util.isEmpty(entity.recvAddr)) {
      entity.recvAddr = entity.content.get(0).addr;
    }
    entity.recvAddr = StaticSql.service.addr.getRecvAddr(entity.recvAddr, per.id);
    entity.oid = "";
    entity.create = per.id;

    entity.name = "购买商品: ";
    entity.money = 0;
    entity.prize = "填充";
    Group g = StaticSql.service.group.getById(entity.gid);
    if (g == null) {
      throw new RuntimeException("商家不存在,请重新下单");
    }
    StaticSql.service.stockLog.check(entity.content, per.id, entity.id, null, entity.gid);

    entity.content.forEach(e -> {
      entity.name += e.goodsName + ", ";
      entity.money += Math.abs(e.sum) * e.goodsMoney;
    });
    if (entity.money >= per.money) {
      entity.balance = per.money.intValue();
      entity.money -= entity.balance;
    } else {
      entity.balance = entity.money;
      entity.money = 0;
    }
    if (entity.money <= 0) {
      entity.payTime = entity.createTime;
    }
    entity.name = entity.name.substring(0, entity.name.length() - 2);
    if (entity.name.length() > 85) {
      entity.name = entity.name.substring(0, 80) + "...";
    }
    if (entity.des == null) {
      entity.des = "";
    }
    entity.prize = "填充";
    entity.prizeGroup = "";
    entity.del = 0;
    return entity;
  }

  public int update(JSONObject p, User per) {
    throw new RuntimeException("接口关闭");
  }

  public Object read(JSONObject p, User per) {
    Page<Order> page = Util.getPage(p, Order.class);
    return page == null ? getList(p, per) : getPage(page, p, per);
  }

  public int delete(JSONObject p, User per) {
    Order entity = this.getById(p.getString("id"));
    if (entity != null) {
      if (entity.create.equals(per.id)) {
        entity.del |= 1;
        String sql = String.format("UPDATE `order` SET `del`=%d WHERE `id`='%s';\n", entity.del, entity.id);
        if (entity.sendTime == 0) {
          if (entity.balance == null || entity.balance == 0) {
            sql = String.format("DELETE FROM `order` WHERE `id` = '%s';\n" +
                "DELETE FROM `stock_log` WHERE `oid` ='%s';\n", entity.id, entity.id);
          } else if ((entity.del & 1) == 0) {
            sql += String.format("UPDATE `user` SET `money`=`money`+%d WHERE `id`='%s';\n", entity.balance, per.id);
          }
        }
        StaticSql.run.safeQuery(sql);
        return 1;
      } else if (per.per("订单删除") || entity.gid.equals(per.gid)) {
        entity.del |= 2;
        this.updateById(new Order(entity.id, entity.del));
        return 1;
      } else {
        throw new RuntimeException("没有权限");
      }
    }
    throw new RuntimeException("订单不存在");
  }

  @Autowired
  WxService wxService;
  @Autowired
  WebSocketService ws;

  @Autowired
  StockMapper sm;

  public JSONObject create(JSONObject p, User per) {
    if (per.wxid == null || per.wxid.length() < 1) {
      throw new RuntimeException("下单前需要绑定微信id");
    }
    Order entity = this.createOrder(p, per);
    JSONObject ret = wxService.create(entity.money, entity.name, entity.id, per.wxid);
    String sql = "";
    if (entity.balance > 0) {
      sql = String.format("UPDATE `user` SET `money`=`money`-'%d' WHERE id='%s';\n", entity.balance, per.id);
    }
    if (ret == null) {
      ret = new JSONObject();
      ret.put("message", "下单成功");
      ret.put("type", "success");
    } else {
      entity.oid = ret.getString("package");
      ret.put("package", "prepay_id=" + ret.getString("package"));
    }
    sql += String.format("%s\n%s", Util.insertSql(
        Arrays.asList(entity), Order.class),
        Util.insertSql(entity.content, StockLog.class));
    StaticSql.run.safeQuery(sql);
    return ret;
  }

  public JSONObject wxpay(JSONObject p, User per) {
    Order entity = this.getById(p.getString("id"));
    if (entity != null && entity.oid != null && entity.oid.length() > 0) {
      JSONObject ret = wxService.did2pd(entity.id, entity.oid);
      String pp = ret.getString("package");
      if (pp != null && entity.payTime == 0) {
        String sql = "", oldid = entity.id;
        entity.id = Util.sGetId();
        entity.createTime = Util.time();

        if (entity.balance == 0 && per.money > 0) {
          if (entity.money >= per.money) {
            entity.balance = per.money.intValue();
            entity.money -= entity.balance;
          } else {
            entity.balance = entity.money;
            entity.money = 0;
          }
          if (entity.balance > 0) {
            sql += String.format("UPDATE `user` SET `money`=`money`-'%d' WHERE id='%s';\n", entity.balance, per.id);
          }
        }
        if (entity.money <= 0) {
          entity.payTime = entity.createTime;
        }
        ret = wxService.create(entity.money, entity.name, entity.id, per.wxid);
        if (ret == null) {
          ret = new JSONObject();
          ret.put("message", "无需支付");
          ret.put("type", "success");
        } else {
          entity.oid = ret.getString("package");
          ret.put("package", "prepay_id=" + ret.getString("package"));
          sql += String.format("%s\n%s\n%s\n",
              Util.insertSql(Arrays.asList(entity), Order.class),
              String.format("UPDATE `stock_log` SET `oid` = '%s' WHERE `oid` = '%s';", entity.id, oldid),
              String.format("DELETE FROM `order` WHERE `id` = '%s';\n", oldid));
          if (entity.balance > 0) {
            sql += String.format("UPDATE `user` SET `money`=`money`+%d WHERE `id`='%s';\n",
                entity.balance, entity.create);
          }
        }
        StaticSql.run.safeQuery(sql);

        return ret;
      }
      setPayTime(entity.id, 0, 1);
      throw new RuntimeException("此单据已支付,请勿重复支付");
    }
    return this.create(p, per);
  }

  public int refresh(JSONObject p, User per) {
    int ret = 0;
    String id = p.getString("id");
    if (id != null) {
      ret = wxService.QueryOrder(id);
      try {
        StaticSql.service.transfer.transferOrder(id);
      } catch (Exception e) {
      }
    }
    return ret;
  }

  /** 设置订单支付时间 */
  public void setPayTime(String id, long payTime, int money) {
    Order order = StaticSql.mapper.order.selectById(id);
    if (order != null) {
      mapper.update(new UpdateWrapper<Order>().eq("id", id).set("pay_time", Util.time()));
      StaticSql.service.transfer.transferOrder(id);
    }
  }

  public Object index(JSONObject p, User per) {
    JSONObject ret = new JSONObject(), xfd = new JSONObject();
    final String[] dx = { "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" };
    xfd.put("label", dx);

    String sql = "SELECT COUNT(*) `value` FROM `order`";
    System.out.println("输出的gid" + StaticSql.service.group.pid(per.gid));
    if (!StaticSql.service.group.pid(per.gid).equals("0")) {
      sql += String.format(" WHERE `oid`='%s'", per.gid);
    }
    ret.put("nums", StaticSql.run.select(sql));
    int year = LocalDate.now().getYear();
    JSONArray a = new JSONArray();
    QueryWrapper<Order> q = new QueryWrapper<Order>();
    for (int i = 1; i < 12; i++) {
      a.add(this.count(q.clone().between("`create_time`",
          Util.time(LocalDate.of(year, i, 1)),
          Util.time(LocalDate.of(year, i + 1, 1)))));
    }
    a.add(this.count(q.clone().ge("`create_time`", Util.time(LocalDate.of(year, 12, 1)))));
    xfd.put("num", a.clone());
    a.clear();
    q.select("id,SUM(`money`) `money`");
    Util.clear();
    List<LinkedHashMap<String, Object>> t;

    for (int i = 1; i < 12; i++) {
      t = StaticSql.run.select(String.format(
          "SELECT SUM(`money`) `money` FROM `order` WHERE `type` = '消费单' AND `create_time` BETWEEN %d AND %d",
          Util.time(LocalDate.of(year, i, 1)), Util.time(LocalDate.of(year, i + 1, 1))));
      if (t.getLast() == null) {
        a.add(0);
      } else {
        a.add(Integer.valueOf(t.getLast().get("money").toString()) / 100);
      }
    }
    t = StaticSql.run.select(String.format(
        "SELECT SUM(`money`) `money` FROM `order` WHERE `type` = '消费单' AND `create_time` BETWEEN %d AND %d",
        Util.time(LocalDate.of(year, 12, 1)), Util.time(LocalDate.of(year + 1, 1, 1))));
    if (t.getLast() == null) {
      a.add(0);
    } else {
      a.add(Integer.valueOf(t.getLast().get("money").toString()) / 100);
    }
    xfd.put("money", a.clone());

    ret.put("xfd", xfd);
    return ret;
  }

  public String getUidById(String id) {
    if (id != null) {
      Order o = mapper.selectOne(new QueryWrapper<Order>().eq("id", id).select("id,`user`"));
      if (o != null) {
        return o.create;
      }
    }
    return null;
  }

  private final String sendSql = "UPDATE `order` SET `send_time`=%s WHERE id='%s';\n";
  private final String sendSql2 = "%d,`send_des`='%s'";
  private final String recvSql = "UPDATE `order` SET `recv_time`=%d WHERE id='%s';\n";

  public Object send(JSONObject p, User per) {
    int ret = 0;
    List<Order> l = mapper.selectList2(readWrapper(p, per));
    String time = p.getString("sendDes");
    if (Util.isEmpty(time)) {
      time = Util.sTime();
    } else {
      time = String.format(sendSql2, Util.time(), Util.safeString(time));
    }
    boolean b = per.per("强制发货");
    StringBuilder sql = new StringBuilder();
    for (Order e : l) {
      if (b || e.gid.equals(per.gid)) { // 商家发货
        wxService.delivery(e.id);
        sql.append(StaticSql.service.stockLog.send(e.id));
        sql.append(String.format(sendSql, time, e.id));
        ret++;
      }
    }
    StaticSql.run.safeQuery(sql.toString());
    // System.out.println(sql.toString());
    return new Message("发货成功", "success", ret);
  }

  public Object recv(JSONObject p, User per) {
    int ret = 0;
    List<Order> l = mapper.selectList2(readWrapper(p, per));
    boolean b = per.per("强制收货");
    final long time = Util.time();
    StringBuilder sql = new StringBuilder();
    for (Order e : l) {
      if (b || e.create.equals(per.id)) { // 消费者收货
        sql.append(StaticSql.service.stockLog.recv(e.id));
        sql.append(String.format(recvSql, time, e.id));
        ret++;
      }
    }
    StaticSql.run.safeQuery(sql.toString());
    return new Message("收货成功", "success", ret);
  }

  public boolean have(String id, User per) {
    QueryWrapper<Order> q = new QueryWrapper<Order>().eq("id", id);
    q.and(e -> {
      e.or().eq("`create`", per.id).or().eq("gid", per.gid).or();
    });
    return this.count(q) == 1;
  }

  public Order addr(JSONObject p, User per) {
    String id = p.getString("id"), aid = p.getString("addr");
    if (!(Util.isEmpty(aid) || Util.isEmpty(id))) {
      Order o = this.getById(id);
      Addr a = StaticSql.service.addr.getById(aid);
      if (o != null && o.create.equals(per.id) && o.recvTime.equals(0l)
          && a != null && a.create.equals(per.id)) {
        a.id = null;
        a.create = null;
        a.createTime = null;
        a.def = null;
        o.recvAddr = Util.toJString(a);
        mapper.update(new UpdateWrapper<Order>().eq("id", o.id).set("`recv_addr`", o.recvAddr));
        return o;
      }
    }
    throw new RuntimeException("没有权限");
  }
}
